import subprocess
import sys
from UI.main import Ui_Main
import pyqtgraph as pg
from Class.cs598 import *
from UIClass.UIDAQ import UIDAQ
from UIClass.UIFilter import UIFilter
from UIClass.UIMultiBaseCalibration import UIMultiBaseCalibration
from UIClass.UIMultiPointCalibration import UIMultiPointCalibration
from UIClass.UICalibration import UICalibration
import os
from Class.VoltSignal import dataBase
from Class.Format import *
from UIClass.UIReport import UIReport
from UIClass.UIBalance import UIBalance
from UIClass.UICompareCurve import UICompareCurve
from Class.PortManager import portManager
from Class.Log import log
from UIClass.UITableSet import UITableSet
from UIClass.UIModifySample import UIModifySample
from UIClass.UIEnterPsw import UIEnterPsw
from UIClass.UIBlank import UIBlank
from Class.GraphBase import GraphBase
from Class.UserInfo import *
from importQT import *
import shelve
from UIClass.UIMethod import UIMethod
from UIClass.UIDevice import UIDevice
from UIClass.UICheckLeckCS import UICheckLeck
from PyQt5.QtSql import QSqlDatabase
import getpath
class UIMain(QtWidgets.QMainWindow, Ui_Main):
    def __init__(self):
        super(UIMain, self).__init__()  # 构造函数super()是必须的，否则就只能调用子窗口的显示，不能调用子窗口中的按钮等控件。
        self.setupUi(self)
        '''
        配置界面
        '''
        # <editor-fold desc="配置界面">
        self.iconFurnaceDown = QIcon()
        self.iconFurnaceDown.addPixmap(QPixmap(":/pic/FurnaceDown.png"), QIcon.Normal, QIcon.On)
        self.iconFurnaceUp = QIcon()
        self.iconFurnaceUp.addPixmap(QPixmap(":/pic/FurnaceUp.png"), QIcon.Normal, QIcon.On)
        self.iconHFGray = QIcon()
        self.iconHFGray.addPixmap(QPixmap(":/pic/高频_灰.png"), QIcon.Normal, QIcon.On)
        self.iconHF = QIcon()
        self.iconHF.addPixmap(QPixmap(":/pic/高频.png"), QIcon.Normal, QIcon.On)
        self.applyResource()
        self.progressBar.setVisible(False)
        self.initTable()
        self.initLines()
        cs_598.sigStatusUpdate.connect(self.deviceStatusUpdate)
        cs_598.sigSetStartEnable.connect(self.setStartEnable)
        cs_598.sigWaitting.connect(self.waittingWindows)
        self.showMaximized()  # 最大化显示
        # </editor-fold>
        self.errorCarrier = "载气流量过低"
        self.errorPressure = "载气压力太低"
        self.connectSlot()
        cs_598.link_card()
        self.bGetWeight = 0  # 0不单独接收质量；1 接收样品质量；2 接收助熔剂质量
        self.chkBalance.setCheckState(Qt.Checked)
        inPutPath = os.path.abspath(sys.argv[0])
        self.balancePath = os.path.join(os.path.dirname(inPutPath) + os.path.sep + "Balance.txt")  # 天平参数文件地址
        self.initBalance()
        self.initLink()
        self.txtMethod.setText(cs_598.config.name)
        # <editor-fold desc="状态栏设置">
        self.lblLiftFurnace = QLabel(self)
        self.lblLiftFurnace.setText("升炉到位")
        self.statusbar.addPermanentWidget(self.lblLiftFurnace)
        self.lblBrush = QLabel(self)
        self.lblBrush.setText("炉刷复位")
        self.statusbar.addPermanentWidget(self.lblBrush)
        self.lblCarrierPressure = QLabel(self)
        self.lblCarrierPressure.setText("载气压力：***")
        self.lblCarrierPressure.setAutoFillBackground(True)
        self.statusbar.addPermanentWidget(self.lblCarrierPressure)
        self.lblMFC = QLabel(self)
        self.lblMFC.setText("载气流量：***")
        self.lblMFC.setAutoFillBackground(True)
        self.lblMFC.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.statusbar.addPermanentWidget(self.lblMFC)
        self.lblReformer = QLabel(self)
        self.lblReformer.setText("转化炉温：***")
        self.statusbar.addPermanentWidget(self.lblReformer)
        self.lblReformer.setVisible(False)
        self.statusbar.addAction(self.actionMultiPointCali)
        # btnMultiPointCali = QPushButton(self)
        # btnMultiPointCali.clicked.connect(self.actionMultiPointCali_triggered)
        # btnMultiPointCali.setStyleSheet("border-style:hidden")
        # self.statusbar.addWidget(btnMultiPointCali)
        # </editor-fold>
    #     self.init_db()
    # def init_db(self):
    #     """
    #     init_db()
    #     Initializes the database.
    #     If tables "books" and "authors" are already in the database, do nothing.
    #     Return value: None or raises ValueError
    #     The error value is the QtSql error instance.
    #     """
    #     db = QSqlDatabase.addDatabase("QSQLITE")
    #     p=getpath.getpath()+"/../data.sqlite"
    #     print(p)
    #     db.setDatabaseName(p)

    def applyResource(self):
        icon = QIcon()
        icon.addPixmap(QPixmap(":/pic/icon.ico"), QIcon.Normal, QIcon.On)
        self.setWindowIcon(icon)
        icon0 = QIcon()
        icon0.addPixmap(QPixmap(":/pic/复位.png"), QIcon.Normal, QIcon.On)
        self.actionReset.setIcon(icon0)
        self.actionReset.setIconVisibleInMenu(False)
        icon2 = QIcon()
        icon2.addPixmap(QPixmap(":/pic/方法.png"), QIcon.Normal, QIcon.On)
        self.actionMethod.setIcon(icon2)
        icon3 = QIcon()
        icon3.addPixmap(QPixmap(":/pic/打开样品.png"), QIcon.Normal, QIcon.On)
        self.actionFilter.setIcon(icon3)
        icon4 = QIcon()
        icon4.addPixmap(QPixmap(":/pic/Print.png"), QIcon.Normal, QIcon.On)
        self.actionReport.setIcon(icon4)
        icon5 = QIcon()
        icon5.addPixmap(QPixmap(":/pic/吸尘.png"), QIcon.Normal, QIcon.On)
        self.actionDush.setIcon(icon5)
        self.actionPower.setIcon(self.iconHFGray)
        self.actionFurnace.setIcon(self.iconFurnaceDown)
        self.actionFurnace.setIconVisibleInMenu(False)
        self.toolBar.setFixedHeight(50)
        self.toolBar.setIconSize(QSize(45, 45))
        self.toolBar.addSeparator()
        self.lblStute = QtWidgets.QLabel(self.widget_2)
        self.lblStute.setGeometry(QtCore.QRect(10, 540, 271, 31))
        self.lblStute.setObjectName("lblStute")
        self.toolBar.addWidget(self.lblStute)
        spacer = QWidget(self)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolBar.addWidget(spacer)
        self.progressBar = QtWidgets.QProgressBar(self.widget_2)
        self.progressBar.setGeometry(QtCore.QRect(0, 510, 300, 31))
        self.progressBar.setMinimumSize(QtCore.QSize(300, 0))
        self.progressBar.setMaximumSize(QtCore.QSize(300, 16777215))
        self.progressBar.setMaximum(10)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.actionProgressBar = self.toolBar.addWidget(self.progressBar)
        self.actionProgressBar.setVisible(False)
        self.groupBox_2.setVisible(False)
        # if currentuser.userlevel != goduser.userlevel:
        #     self.actionBaseCali.setVisible(False)

    def initBalance(self):
        portManager.init(self.balancePath)
        res = portManager.open()
        if isinstance(res, bool):
            if not res:
                self.showStatus("天平连接失败")
                log.error("天平", "天平连接失败")
        else:
            self.showStatus("无法找到天平串口")
            log.error("天平", res)
            pass
        portManager.sigSendWeight.connect(self.Balance_DataReceived)

    def initLink(self):
        if not cs_598.card.isLinked:
            self.setLinked(False)
            # QMessageBox.critical(self, "提示", "采集卡未连接")
        else:
            self.setLinked(True)

    # <editor-fold desc="曲线">
    def initLines(self):
        self.graphBase1 = GraphBase(self, title='释放曲线')
        self.curveWidget = self.graphBase1.graphwiget
        self.curveline_list = [list(), list(), list(), list()]
        self.curveLine_T = [list(), list(), list(), list()]
        self.horizontalLayout.addWidget(self.curveWidget)
        self.curveWidget.addLegend()
        self.curve = [self.curveWidget.plot(pen=pg.mkPen(color=(128, 0, 0), width=2), name="LC"),
                      self.curveWidget.plot(pen=pg.mkPen(color=(30, 144, 255), width=2), name="HC"),
                      self.curveWidget.plot(pen=pg.mkPen(color=(255, 0, 255), width=2), name="LS"),
                      self.curveWidget.plot(pen=pg.mkPen(color=(255, 0, 0), width=2), name="HS")]
        self.curveLine_setVisiable(0, False)
        self.curveLine_setVisiable(1, False)
        self.curveLine_setVisiable(2, False)
        self.curveLine_setVisiable(3, False)
        self.curveWidget.plotItem.legend.setOffset((-0.1, 30))
        # 第一个参数标识左右，负值表示离右边的像素吧？第二个参数表示上下
        # </editor-fold>
        # <editor-fold desc="基线">
        self.graphBase2 = GraphBase(self, title='基线')
        self.baseWidget = self.graphBase2.graphwiget
        # self.baseWidget.setLabel("left", "U/v")
        # self.baseWidget.setLabel("bottom", "T/s")
        self.baseline_list = [list(), list(), list(), list()]
        self.baseline_t = list()
        self.baseline_count = 0
        self.horizontalLayout.addWidget(self.baseWidget)
        self.baseWidget.addLegend()
        self.base = [self.baseWidget.plot(pen=pg.mkPen(color=(128, 0, 0), width=2), name="LC"),
                     self.baseWidget.plot(pen=pg.mkPen(color=(30, 144, 255), width=2), name="HC"),
                     self.baseWidget.plot(pen=pg.mkPen(color=(255, 0, 255), width=2), name="LS"),
                     self.baseWidget.plot(pen=pg.mkPen(color=(255, 0, 0), width=2), name="HS")]
        self.baseWidget.plotItem.legend.setOffset((-0.1, 30))
        # </editor-fold>

        cs_598.sigBaseLineUpdate.connect(self.baseline_update)
        cs_598.sigCurveLineAddPoint.connect(self.curveLine_addPoint)

        # <editor-fold desc="右键菜单">
        action2 = QAction("强制分析", self.baseWidget)
        action2.setCheckable(True)
        action2.triggered.connect(self.chkForce_stateChanged)
        self.baseWidget.addAction(action2)
        # </editor-fold>
        self.baseLine_setVisiables()

    def curveLine_addPoint(self, i, t, v):
        """
        释放曲线增加一点，当通道i==-1时，清除界面曲线，开放所有通道
        :param i:
        :param t:
        :param v:
        :return:
        """
        if i == -1:  # 清除界面曲线
            self.curveLine_clearLines()
            self.setCheck(0x0F)  # 开启所有通道
        else:
            self.curveline_list[i].append(v)
            self.curveLine_T[i].append(t)
            self.curve[i].setData(x=self.curveLine_T[i], y=self.curveline_list[i])

    def curveLine_addPoints(self, i, ts, vs):
        self.curveline_list[i].clear()
        self.curveline_list[i].extend(vs)
        self.curveLine_T[i].clear()
        self.curveLine_T[i].extend(ts[:len(vs)])
        self.curve[i].setData(x=self.curveLine_T[i], y=self.curveline_list[i])

    def curveLine_zoom(self):
        self.curveWidget.getPlotItem().vb.autoRange()
        self.curveWidget.getPlotItem().enableAutoRange(x=True, y=True)

    def curveLine_setVisiable(self, i, visiable):
        if visiable:
            self.curve[i].show()
        else:
            self.curve[i].hide()

    def baseLine_setVisiables(self):
        for i in range(dataBase.maxChannel):
            if cs_598.config.channels[i].enable:
                self.base[i].show()
            else:
                self.base[i].hide()

    def curveLine_clearLines(self):
        '''清除释放曲线数据列表'''
        for i in range(dataBase.maxChannel):
            self.curveline_list[i].clear()
            self.curveLine_T[i].clear()
            self.curve[i].setData(x=self.curveLine_T[i], y=self.curveline_list[i])

    def baseline_update(self, data):
        if not cs_598.enableAcq:
            self.baseline_count += 1
            if self.baseline_count > 50:
                self.baseline_t[:-1] = self.baseline_t[1:]  # 取第二位到结束这个切片，从第0位开始覆盖
                self.baseline_t.pop()
            self.baseline_t.append(self.baseline_count / cs_598.systemconfig.daq.freq)
            for i in range(0, dataBase.maxChannel):
                if self.baseline_count > 50:
                    self.baseline_list[i][:-1] = self.baseline_list[i][1:]  # 取第二位到结束这个切片，从第0位开始覆盖
                    self.baseline_list[i].pop()
                    # self.base[i].setPos(self.baseline_t[self.baseline_count-50], 0)
                self.baseline_list[i].append(data[2][i])
                self.base[i].setData(self.baseline_t, self.baseline_list[i])

    # </editor-fold>

    # <editor-fold desc="表格">

    def initTable(self):
        setupTable(self.tableView, cs_598.modelResult, cs_598.settings.resultcolHidden)
        self.tableView.sigMouseLeft.connect(self.tableView_currentChange)
        self.tableView.sigMouseRightMove.connect(self.tableView_grag)
        self.tableView.sigKeyUpDown.connect(self.tableView_currentChange)
        # for col in cs_598.settings.resultcolHidden:
        #     self.tableView.setColumnHidden(col, True)
        """不可用选择改变事件去处理，因为每多选一行，就会触发一次
        s=self.tableView.selectionModel()
        s.selectionChanged.connect(self.tableView_currentChange)
        """
        self.tableView.setColumnHidden(dataBase.dbColUser[1], True)

    def tableView_grag(self):
        """结果列表拖拽槽"""
        sModel = self.tableView.selectionModel()
        rowIndex = sModel.selectedRows()
        if len(rowIndex) > 0:
            s = ""
            for index in rowIndex:
                if s != "":
                    s += "&"
                s += str(index.row())

        data = QMimeData()
        data.setText(s)
        drag = QDrag(self)
        drag.setMimeData(data)
        drag.exec()

    def tableView_currentChange(self):
        s = self.tableView.selectionModel()
        rowIndex = s.selectedRows()
        count = len(rowIndex)
        if count == 1:
            index = rowIndex[0]
            id = cs_598.modelResult.item(index.row(), dataBase.dbColId[1]).data(0)
            vs = VoltSignal.loadAll(id)
            if vs is not None:
                if self.chkcali.checkState() == Qt.Checked:
                    channel = str(cs_598.modelResult.item(index.row(), dataBase.dbColChannel[1]).data(0))
                    col = dataBase.dbColReLE1[1]
                    if channel.find("HC") != -1:
                        col = dataBase.dbColReHE1[1]
                    self.setResultE1(cs_598.modelResult.item(index.row(), col).data(0))
                    col = dataBase.dbColReLE2[1]
                    if channel.find("HS") != -1:
                        col = dataBase.dbColReHE2[1]
                    self.setResultE2(cs_598.modelResult.item(index.row(), col).data(0))
                else:
                    self.setResultE1(cs_598.modelResult.item(index.row(), dataBase.dbColE1[1]).data(0))
                    self.setResultE2(cs_598.modelResult.item(index.row(), dataBase.dbColE2[1]).data(0))
                if not cs_598.enableAcq:
                    self.setCheck(vs.result.Channel)
                    for i in range(0, dataBase.maxChannel):
                        if vs.channels[i]:
                            self.curveLine_addPoints(i, vs.listT, vs.listData[i])
        elif count > 1:
            # 计算平均值、sd、rsd
            e1 = []
            e2 = []
            for index in rowIndex:
                if self.chkcali.checkState() == Qt.Checked:
                    channel = str(cs_598.modelResult.item(index.row(), dataBase.dbColChannel[1]).data(0))
                    col = dataBase.dbColReLE1[1]
                    if channel.find("HC") != -1:
                        col = dataBase.dbColReHE1[1]
                    e1.append(cs_598.modelResult.item(index.row(), col).data(0))
                    col = dataBase.dbColReLE2[1]
                    if channel.find("HS") != -1:
                        col = dataBase.dbColReHE2[1]
                    e2.append(cs_598.modelResult.item(index.row(), col).data(0))
                else:
                    e1.append(cs_598.modelResult.item(index.row(), dataBase.dbColE1[1]).data(0))
                    e2.append(cs_598.modelResult.item(index.row(), dataBase.dbColE2[1]).data(0))
            avr1 = Factor.calculateAverage(e1)
            dev1 = Factor.calculateDeviation(e1)
            rsd1 = Factor.calculateRSD(dev1, avr1)
            self.lblValue1.setText(Format.result(avr1, True))
            self.lblDevE1.setText(Format.result(dev1, True))
            self.lblReDevE1.setText(Format.percent(rsd1, True))
            avr2 = Factor.calculateAverage(e2)
            dev2 = Factor.calculateDeviation(e2)
            rsd2 = Factor.calculateRSD(dev2, avr2)
            self.lblValue2.setText(Format.result(avr2, True))
            self.lblDevE2.setText(Format.result(dev2, True))
            self.lblReDevE2.setText(Format.percent(rsd2, True))

    def getSelection(self):
        '''
        获取结果列表中选中行de ids
        :return: []结果列表中选中行的ids,未选中时，提示，返回NONE
        '''
        s = self.tableView.selectionModel()
        rowIndex = s.selectedRows()
        count = len(rowIndex)
        if count == 0:
            QMessageBox.warning(self, '提示', "请选择数据")
            return None
        else:
            ids = []
            for index in rowIndex:
                ids.append(cs_598.modelResult.item(index.row(), 0).data(0))
            return ids

    # </editor-fold>
    def connectSlot(self):
        self.actionExit.triggered.connect(self.actionExit_triggered)
        self.actionDAQ.triggered.connect(self.actionDAQ_triggered)
        self.actionFilter.triggered.connect(self.actionFilter_triggered)
        self.actionReset.triggered.connect(self.actionReset_triggered)
        self.actionFurnace.triggered.connect(self.actionFurnace_triggered)
        self.actionDush.triggered.connect(self.actionDush_triggered)
        self.actionCheckLeck.triggered.connect(self.actionCheckLeck_triggered)
        self.actionClearResult.triggered.connect(self.actionClearResult_triggered)
        self.actionBaseCali.triggered.connect(self.actionBaseCali_triggered)
        self.actionSingleCali.triggered.connect(self.actionSingleCali_triggered)
        self.actionMultiPointCali.triggered.connect(self.actionMultiPointCali_triggered)
        self.actionBlank.triggered.connect(self.actionBlank_triggered)
        self.actionReCalculate.triggered.connect(self.actionReCalculate_triggered)
        self.actionDebugDevice.triggered.connect(self.actionDebugDevice_triggered)
        self.actionMethod.triggered.connect(self.actionMethod_triggered)
        self.actionReport.triggered.connect(self.actionReport_triggered)
        self.actionBalance.triggered.connect(self.actionBalance_triggered)
        self.actionExport.triggered.connect(self.actionExport_triggered)
        self.actionPower.triggered.connect(self.actionPower_triggered)
        self.actionCompare.triggered.connect(self.actionCompare_triggered)
        self.actionAbout.triggered.connect(self.actionAbout_triggered)
        self.actionTableSet.triggered.connect(self.actionTableSet_triggered)
        self.actionModifySample.triggered.connect(self.actionModifySample_triggered)
        self.actionHelp.triggered.connect(self.actionHelp_triggered)

        self.btnStart.clicked.connect(self.btnStart_clicked)
        self.btnStop.clicked.connect(self.btnStop_clicked)
        self.btnWeight.clicked.connect(self.btnWeight_clicked)
        self.btnFlux.clicked.connect(self.btnWeight_clicked)

        self.chk0.stateChanged.connect(self.chk_stateChanged)
        self.chk1.stateChanged.connect(self.chk_stateChanged)
        self.chk2.stateChanged.connect(self.chk_stateChanged)
        self.chk3.stateChanged.connect(self.chk_stateChanged)

        self.chkcali.stateChanged.connect(self.tableView_currentChange)

        cs_598.sigStatusTip.connect(self.showStatus)
        cs_598.sigUpdateNewResult.connect(self.updateAll)

    # <editor-fold desc="动作槽函数">
    def actionCheckLeck_triggered(self):
        if not cs_598.card.isLinked:
            QMessageBox.information(self, "提示", "采集卡未连接")
            return
        w = UICheckLeck()
        w.setAttribute(Qt.WA_DeleteOnClose)
        w.exec()

    def actionHelp_triggered(self):
        inPutPath = os.path.dirname(os.path.abspath(sys.argv[0]))  # 程序运行的绝对路径
        filepath = os.path.join(inPutPath, "使用说明书.pdf")
        if os.path.exists(filepath):
            try:
                subprocess.Popen(["xdg-open", filepath])  # 调用系统默认工具，打开文件
            except:
                QMessageBox.information(self, "提示", "文件打开失败")
        else:
            QMessageBox.information(self, "提示", "未找到使用说明书。")

    def actionModifySample_triggered(self):
        ids = self.getSelection()
        if ids is not None:
            psw: str
            m = UIEnterPsw()
            m.setAttribute(Qt.WA_DeleteOnClose)
            if m.exec():
                psw = m.psw
                if psw == adminuser.psw or psw == goduser.psw:
                    result = []
                    w = UIModifySample(result, psw == goduser.psw)
                    w.setAttribute(Qt.WA_DeleteOnClose)
                    if w.exec():
                        rs = []
                        for id in ids:
                            r = VoltSignal.loadResult(id)
                            if r != None:
                                rs.append(r)
                            else:
                                log.error("修改样品信息", "找不到数据")
                        for r in rs:
                            r: DBResult
                            if result[0] is not None:
                                r.SampleName = str(result[0])
                            if result[1] is not None:
                                r.SampleNum = str(result[1])
                            if result[2] is not None:
                                r.SampleWeight = float(result[2])
                            if result[3] is not None:
                                r.FluxWeight = float(result[3])
                        if len(rs) != 0 and VoltSignal.updateSampleInfo(rs):
                            cs_598.updateResults(rs)
                            QMessageBox.information(self, "提示", "修改成功")
                        else:
                            QMessageBox.information(self, "提示", "修改失败")

    def actionTableSet_triggered(self):
        w = UITableSet()
        w.setAttribute(Qt.WA_DeleteOnClose)
        w.exec()
        for i in range(dataBase.colNum):
            if i in cs_598.settings.resultcolHidden:
                self.tableView.setColumnHidden(i, True)
            else:
                self.tableView.setColumnHidden(i, False)

    def actionCompare_triggered(self):
        self.w = UICompareCurve()
        self.w.setAttribute(Qt.WA_DeleteOnClose)
        self.w.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.w.show()

    def actionExport_triggered(self):
        s = self.tableView.selectionModel()
        rowIndex = s.selectedRows()
        count = len(rowIndex)
        if count > 0:
            # 获取保存文件夹
            dirpath = QFileDialog.getExistingDirectory(self, "选择保存路径")
            if dirpath != "":
                for index in rowIndex:
                    id = cs_598.modelResult.item(index.row(), dataBase.dbColId[1]).data(0)
                    vs = VoltSignal.loadAll(id)
                    if vs is not None:
                        data = []
                        id1 = vs.sampleId.strftime("%Y%m%d%H%M%S")
                        data.append(id1)
                        data.append(vs.sampleName + "," + str(vs.sampleNum) + "," + str(vs.sampleWeight) + "," + str(
                            vs.fluxWeight))
                        data.append(Format.value6decim(vs.average[0]) + "," +
                                    Format.value6decim(vs.average[1]) + "," +
                                    Format.value6decim(vs.average[2]) + "," +
                                    Format.value6decim(vs.average[3]) + ","
                                    )
                        data.append(Format.value6decim(vs.AverageVs[0]) + "," +
                                    Format.value6decim(vs.AverageVs[1]) + "," +
                                    Format.value6decim(vs.AverageVs[2]) + "," +
                                    Format.value6decim(vs.AverageVs[3]) + ","
                                    )

                        data.append("时间，通道1，通道2，通道3， 通道4")
                        count = len(vs.listT)
                        count1 = len(vs.listData[0])
                        count2 = len(vs.listData[1])
                        count3 = len(vs.listData[2])
                        count4 = len(vs.listData[3])
                        for i in range(count):
                            d1 = Format.value6decim(vs.listData[0][i]) if count1 > i else ""
                            d2 = Format.value6decim(vs.listData[1][i]) if count2 > i else ""
                            d3 = Format.value6decim(vs.listData[2][i]) if count3 > i else ""
                            d4 = Format.value6decim(vs.listData[3][i]) if count4 > i else ""

                            data.append(('%.1f' % vs.listT[i]) + "," + d1 + "," + d2 + "," + d3 + "," + d4)
                        data.append("+++++++++++++++++++++++++++++++++++++++++++++++++++++++")
                        for i in range(dataBase.maxChannel):
                            d = ""
                            for v in vs.DataChannelDelay[i]:
                                d += Format.value6decim(v) + ","
                            data.append(d)
                        with open(os.path.join(dirpath, id1 + ".txt"), "w") as f:
                            for i in data:
                                f.write(i + os.linesep)
        else:
            QMessageBox.information(self, "", "请选择数据")

    def actionExit_triggered(self):
        self.close()

    def btnWeight_clicked(self):
        if not self.btnWeight.isEnabled():
            return
        self.bGetWeight = 1 if self.sender() is self.btnWeight else 2
        self.chkBalance.setCheckState(Qt.Unchecked)

    def actionBalance_triggered(self):
        w = UIBalance()
        w.setAttribute(Qt.WA_DeleteOnClose)
        w.exec()
        if not portManager.isOpened():
            self.showStatus("天平未连接")

    def actionReport_triggered(self):
        self.uiReport = UIReport()
        self.uiReport.setAttribute(Qt.WA_DeleteOnClose)
        self.uiReport.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.uiReport.show()

    def chkForce_stateChanged(self):
        cs_598.baseData.forceAnalyse = bool(1 - cs_598.baseData.forceAnalyse)

    def actionMethod_triggered(self):
        w = UIMethod()
        w.setAttribute(Qt.WA_DeleteOnClose)
        w.exec()
        self.baseLine_setVisiables()
        Format.decimals = cs_598.config.decimals
        self.tableView.update()
        self.txtMethod.setText(cs_598.config.name)

    def actionDebugDevice_triggered(self):
        if not cs_598.card.isLinked:
            QMessageBox.information(self, "提示", "采集卡未连接")
        w = UIDevice()
        w.setAttribute(Qt.WA_DeleteOnClose)
        w.exec()

    def actionReCalculate_triggered(self):
        ids = self.getSelection()
        if ids is not None:
            rs = []
            for id in ids:
                vs = VoltSignal.loadAll(id)
                if vs != None:
                    value = []
                    for i in range(dataBase.maxChannel):
                        value.append(cs_598.config.factors[i].calculateResult(vs.listT, vs.listData[i],
                                                                              vs.sampleWeight,
                                                                              vs.average[i], vs.fluxWeight))
                    vs.Results0 = value
                    rs.append(vs.result)
                else:
                    log.error("重新计算", "找不到数据")
            if len(rs) != 0 and VoltSignal.updateResults(rs):
                cs_598.updateResults(rs)
                self.tableView_currentChange()
                QMessageBox.information(self, "提示", "请查看校正后结果")
            else:
                QMessageBox.information(self, "提示", "重新计算失败")

    def actionSingleCali_triggered(self):
        ids = self.getSelection()
        if ids is not None:
            w = UICalibration(ids)
            w.setAttribute(Qt.WA_DeleteOnClose)
            w.exec()

    def actionBlank_triggered(self):
        ids = self.getSelection()
        if ids is not None:
            w = UIBlank(ids)
            w.setAttribute(Qt.WA_DeleteOnClose)
            w.exec()

    def actionBaseCali_triggered(self):
        self.uiMultiBase = UIMultiBaseCalibration()
        self.uiMultiBase.setAttribute(Qt.WA_DeleteOnClose)
        self.uiMultiBase.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.uiMultiBase.show()

    def actionMultiPointCali_triggered(self):
        self.uiMultiPoint = UIMultiPointCalibration()
        self.uiMultiPoint.setAttribute(Qt.WA_DeleteOnClose)
        self.uiMultiPoint.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.uiMultiPoint.show()

    def actionClearResult_triggered(self):
        indexs = self.tableView.selectionModel().selectedRows()  # 获取被选中行
        cs_598.modelResult.removeRowsByIndex(indexs)

    def btnStop_clicked(self):
        cs_598.analyse_stop()

    def btnStart_clicked(self, checked):
        if not self.btnStart.isEnabled():
            return
        #检查是是否有异常
        if not self.checkStatus():
            cs_598.autoStatus == 0
            return
        if not cs_598.bHFPower:
            QMessageBox.information(self, "提示", "请先打开灯丝电源")
            return
        if cs_598.bPreHeating:
            QMessageBox.information(self, "提示", "等待高频预热")
            return
        sample = SampleInfo()
        sample.sampleName = self.txtSampleName.text()
        try:
            sample.sampleWeight = float(self.txtSampleWeight.text())
            if sample.sampleWeight <= 0:
                raise Exception("样品质量异常！")
            sample.sampleNum = int(self.txtSampleNo.text())
            sample.fluxWeight = float(self.txtSampleFlux.text())
        except Exception as ex:
            QMessageBox.warning(self, "提示", "样品信息异常")
            return
        self.setStartEnable(False)
        self.txtSampleWeight.setText("0")
        self.txtSampleFlux.setText("0")
        if self.chkAuto.checkState() == Qt.Checked:
            self.txtSampleNo.setText(str(sample.sampleNum + 1))
        cs_598.analyseStart(sample)

    def actionFilter_triggered(self):
        w = UIFilter()
        result = w.exec()
        if result == 1:
            count = cs_598.modelResult.rowCount()
            cs_598.modelResult.removeRows(0, count)
            rowIndexs = w.modelSelect.selectedRows()
            cs_598.modelResult.addRow(w.model, rowIndexs)
            # self.tableView.update()

    def actionDush_triggered(self):
        cs_598.exhausterOperation()

    def actionDAQ_triggered(self):
        w = UIDAQ()
        w.setWindowModality(QtCore.Qt.ApplicationModal)
        # 模态对话框，不关闭此对话框，不能执行别的操作。
        w.exec()
        self.initLink()

    def actionReset_triggered(self):
        if not self.actionReset.isEnabled():
            return
        self.setStartEnable(False)
        cs_598.reset()

    def actionFurnace_triggered(self):
        if not self.actionFurnace.isEnabled():
            return
        self.setStartEnable(False)
        cs_598.furnaceOperation()

    def actionPower_triggered(self):
        if not self.actionPower.isEnabled():
            return
        if cs_598.hfPowerOperation():
            self.actionPower.setIcon(self.iconHF)
        else:
            self.actionPower.setIcon(self.iconHFGray)

    def actionAbout_triggered(self):
        QMessageBox.information(self, "提示", "软件版本：CS598v0.0.0.1")

    def chk_stateChanged(self, checkState):
        channel = -1
        if self.sender() == self.chk0:
            channel = 0
        elif self.sender() == self.chk1:
            channel = 1
        elif self.sender() == self.chk2:
            channel = 2
        elif self.sender() == self.chk3:
            channel = 3
        if channel != -1:
            self.curveLine_setVisiable(channel, checkState == Qt.Checked)
            self.curveLine_zoom()

    # </editor-fold>

    # <editor-fold desc="自定义信号槽函数">
    def Balance_DataReceived(self, value):
        if self.chkBalance.checkState() == Qt.Checked:  # 自动读数
            if value < 1.0:  # 样品重量
                self.txtSampleWeight.setText(Format.weight(value))
            elif value < 10:  # 助熔剂重量会减去样品重量
                weight = 0.0
                try:
                    if self.txtSampleWeight.text() != "":
                        weight = float(self.txtSampleWeight.text())
                except ValueError:
                    print("Not a float")
                self.txtSampleFlux.setText(Format.weight(value - weight))
        else:  # 单次读数
            if self.bGetWeight == 1:
                self.txtSampleWeight.setText(Format.weight(value))
                self.bGetWeight = 0
            elif self.bGetWeight == 2:
                weight = 0.0
                try:
                    if self.txtSampleWeight.text() != "":
                        weight = float(self.txtSampleWeight.text())
                except ValueError:
                    print("Not a float")
                self.txtSampleFlux.setText(Format.weight(value - weight))
                self.bGetWeight = 0

    def deviceStatusUpdate(self, monitor):
        monitor:Monitor
        """更新界面的仪器状态，以背景色的不同标识开启状态"""
        if monitor.DILiftFurnace:
            self.lblLiftFurnace.setStyleSheet("background-color:#00FFFF")
            self.actionFurnace.setIcon(self.iconFurnaceUp)
        else:
            self.lblLiftFurnace.setStyleSheet("background-color:#F0F8FF")
            self.actionFurnace.setIcon(self.iconFurnaceDown)
        if monitor.DIBrush:
            self.lblBrush.setStyleSheet("background-color:#00FFFF")
        else:
            self.lblBrush.setStyleSheet("background-color:#F0F8FF")
        self.lblCarrierPressure.setText(('载气压力：%.2f' % monitor.ADPressure) + "MPa")
        self.lblMFC.setText(('载气流量：%.2f' % monitor.ADFlow) + "L/min")
        pe_RED = QPalette()
        pe_RED.setColor(QPalette.Background, Qt.red)
        pe_T = QPalette()
        pe_T.setColor(QPalette.Background, Qt.transparent)
        if monitor.errorcarrierpressure:
            self.lblCarrierPressure.setPalette(pe_RED)
            if (not cs_598.analyseStop) and (not cs_598.bFurnaceUp):
                cs_598.analyse_stop()
                QMessageBox.warning(self, "提示", self.errorPressure)
        else:
            self.lblCarrierPressure.setPalette(pe_T)
        if monitor.errorcarrier:
            self.lblMFC.setPalette(pe_RED)
            if not cs_598.analyseStop:
                cs_598.analyse_stop()
                QMessageBox.warning(self, "提示", self.errorCarrier)
        else:
            self.lblMFC.setPalette(pe_T)

    def checkStatus(self):
        errors = ""
        if cs_598.monitor.errorcarrier:
            errors += self.errorCarrier+";"
        if cs_598.monitor.errorcarrierpressure:
            errors += self.errorPressure+";"
        if errors != "":
            QMessageBox.warning(self, "提示", errors)
            return False
        return True

    def updateAll(self, r):
        '''结果列表新增一行结果r;设置左侧结果的显示；设置通道面板的选择状态；使能分析按钮'''
        if r is not None:
            self.tableView.update()
            self.tableView.scrollToBottom()
            rows = cs_598.modelResult.rowCount()
            self.tableView.selectRow(rows - 1)
            self.setResultE1(r.Content01)
            self.setResultE2(r.Content02)
            self.setCheck(r.Channel)
        self.setStartEnable(True)

    def setResultE1(self, e):
        self.lblValue1.setText(Format.result(e, True))
        self.lblDevE1.setText("***")
        self.lblReDevE1.setText("***")

    def setResultE2(self, e):
        self.lblValue2.setText(Format.result(e, True))
        self.lblDevE2.setText("***")
        self.lblReDevE2.setText("***")

    def showStatus(self, s):
        self.lblStute.setText("当前状态："+s)
        if s == "升炉失败":
            QMessageBox.warning(self,"提示",s)
        pass

    # </editor-fold>

    def setCheck(self, flag):
        '''设置通道的选择状态, enble = True,同时设置可用状态'''
        b0 = (flag & 0x01) == 0x01
        self.chk0.setChecked(b0 and cs_598.config.channels[0].enable)
        self.curveLine_setVisiable(0, b0)
        b1 = (flag & 0x02) == 0x02
        self.chk1.setChecked(b1 and cs_598.config.channels[1].enable)
        self.curveLine_setVisiable(1, b1)
        b2 = (flag & 0x04) == 0x04
        self.chk2.setChecked(b2 and cs_598.config.channels[2].enable)
        self.curveLine_setVisiable(2, b2)
        b3 = (flag & 0x08) == 0x08
        self.chk3.setChecked(b3 and cs_598.config.channels[3].enable)
        self.curveLine_setVisiable(3, b3)
        self.curveLine_zoom()

    def setStartEnable(self, enable):
        self.btnStart.setEnabled(enable)
        self.actionFurnace.setEnabled(enable)
        self.actionReset.setEnabled(enable)
        self.actionDush.setEnabled(enable)
        # self.menuDevice.setEnabled(enable)
        self.actionPower.setEnabled(enable)

    def closeEvent(self, event):
        # res = QMessageBox.warning(self, "提示","确定要退出吗？",QMessageBox.Yes, QMessageBox.No)
        # if res != QMessageBox.Yes:
        # # messageBox = QMessageBox()
        # # messageBox.setWindowTitle('提示 ')
        # # messageBox.setText('确定要退出吗')
        # # messageBox.setIcon(QMessageBox.Question)
        # # messageBox.addButton(QPushButton('确定'), QMessageBox.YesRole)
        # # messageBox.addButton(QPushButton('取消'), QMessageBox.NoRole)
        # # if messageBox.exec() == 1:
        #     event.ignore()
        # else:
        if cs_598.card.isLinked:
            cs_598.close_card()
        portManager.close()
        portManager.saveParam(self.balancePath)

    def keyPressEvent(self, keyEvent: QKeyEvent) -> None:
        """键盘按键解析"""
        # print(f"键盘按键：{keyEvent.text()},0X{keyEvent.key():X} 被按下")
        if keyEvent.key() == Qt.Key_F5:
            self.btnStart.click()
            pass
        if keyEvent.key() == Qt.Key_F2:
            self.actionFurnace.trigger()
            pass
        if keyEvent.key() == Qt.Key_F4:
            self.btnWeight.click()
            pass
        if keyEvent.key() == Qt.Key_Escape:
            self.btnStop.click()
            pass
        if keyEvent.key() == Qt.Key_Delete and self.tableView.hasFocus():
            self.actionClearResult.trigger()

    def setLinked(self, linked):
        self.actionReset.setEnabled(linked)
        self.actionDush.setEnabled(linked)
        self.actionFurnace.setEnabled(linked)
        self.btnStart.setEnabled(linked)
        self.actionPower.setEnabled(linked)

    def waittingWindows(self, time):
        if time == 10:
            self.actionProgressBar.setVisible(False)
        else:
            if time == 1:
                self.actionProgressBar.setVisible(True)
                self.progressBar.show()
                self.progressBar.setRange(0, 10)
            self.progressBar.setValue(time)
